home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / PowerPlant / HMarqueeCaption 1.1 / HMarqueeCaption.cp < prev    next >
Encoding:
Text File  |  1997-07-15  |  15.6 KB  |  624 lines  |  [TEXT/CWIE]

  1. /*******************************************************************************\
  2. |                                                                                |
  3. |    HMarqueeCaption.cp ©1997 John C. Daub. All rights reserved.                    |
  4. |    See the file "HMarqueeCaption README" for full details, instructions,        |
  5. |    changes, licensing agreement, etc.  Due to the important information        |
  6. |    included in that file, if you did not receive a copy of it, please contact    |
  7. |    the author for a copy.                                                        |
  8. |                                                                                |
  9. |    John C. Daub <mailto:hsoi@eden.com>                                            |
  10. |    <http://www.eden.com/~hsoi/>  <http://www.eden.com/~hsoi/prog.html>            |
  11. |                                                                                |
  12. \*******************************************************************************/
  13.  
  14.  
  15. #ifdef PowerPlant_PCH
  16. #include PowerPlant_PCH
  17. #endif
  18.  
  19. #include "HMarqueeCaption.h"
  20.  
  21. #include <PP_KeyCodes.h>
  22. #include <UDrawingState.h>
  23. #include <UTextTraits.h>
  24. #include <UMemoryMgr.h>
  25.  
  26. #ifndef __TEXTUTILS__
  27. #include <TextUtils.h>
  28. #endif
  29.  
  30.  
  31. #if ( __PowerPlant__ < 0x01608000 ) // version 1.6/CW11
  32.  
  33. //============================================================================
  34. //    • CreateFromStream                                [static, public]
  35. //============================================================================
  36. //    Create a new Caption object from the data in a Stream
  37.  
  38. HMarqueeCaption*
  39. HMarqueeCaption::CreateFromStream(
  40.     LStream    *inStream)
  41. {
  42.     return (new HMarqueeCaption(inStream));
  43. }
  44.  
  45. #endif
  46.  
  47.  
  48. //============================================================================
  49. //    • HMarqueeCaption                                [public]
  50. //============================================================================
  51. //    Default Constructor
  52.  
  53. HMarqueeCaption::HMarqueeCaption()
  54.     : mStrHeight(0),
  55.     mLastEvent(0),
  56.     mGWorld(nil),
  57.     mTextLength(0),
  58.     mOffset(0),
  59.     mTextH(nil),
  60.     mTextID(0),
  61.     mTextTraitsID(0),
  62.     mDelay(1),
  63.     mScrollAmount(1),
  64.     mResetOnResize(false)
  65. {
  66.     InitMarqueeCaption();
  67. }
  68.  
  69.  
  70. //============================================================================
  71. //    • HMarqueeCaption                                [public]
  72. //============================================================================
  73. //    Copy Constructor
  74.  
  75. HMarqueeCaption::HMarqueeCaption(
  76.     const HMarqueeCaption &inOriginal)
  77.         : LPane(inOriginal),
  78.         mStrHeight(inOriginal.mStrHeight),
  79.         mLastEvent(inOriginal.mLastEvent),
  80.         mGWorld(nil),    // make our own GWorld,
  81.         mOffset(inOriginal.mOffset),
  82.         mTextID(inOriginal.mTextID),
  83.         mTextTraitsID(inOriginal.mTextTraitsID),
  84.         mDelay(inOriginal.mDelay),
  85.         mScrollAmount(inOriginal.mScrollAmount),
  86.         mResetOnResize( inOriginal.mResetOnResize)
  87. {
  88.     // it'll make it's own copy of the text
  89.     
  90.     mTextH = inOriginal.mTextH;
  91.     ThrowIfOSErr_(::HandToHand( &mTextH ));
  92.     SetTextLength();
  93.         
  94.     InitMarqueeCaption();
  95. }
  96.  
  97.  
  98. HMarqueeCaption&
  99. HMarqueeCaption::operator=(
  100.     const HMarqueeCaption &inOriginal )
  101. {
  102.     // prevent self-assignment
  103.     
  104.     if ( this == &inOriginal ) {
  105.         return *this;
  106.     }
  107.     
  108.     // pass it back up
  109.     
  110.     LPane::operator=(inOriginal);
  111.     
  112.     // init our stuff
  113.     
  114.     mStrHeight = inOriginal.mStrHeight;
  115.     mLastEvent = inOriginal.mLastEvent;
  116.     mOffset = inOriginal.mOffset;
  117.     mTextID = inOriginal.mTextID;
  118.     mTextTraitsID = inOriginal.mTextTraitsID;
  119.     mDelay = inOriginal.mDelay;
  120.     mScrollAmount = inOriginal.mScrollAmount;
  121.     mResetOnResize = inOriginal.mResetOnResize;
  122.     
  123.     // it'll make it's own copy of the text
  124.     
  125.     mTextH = inOriginal.mTextH;
  126.     ThrowIfOSErr_(::HandToHand( &mTextH ));
  127.     SetTextLength();
  128.         
  129.     // it'll also make it's own GWorld
  130.     
  131.     mGWorld = nil;
  132.     
  133.     InitMarqueeCaption();
  134.     
  135.     return *this;
  136. }
  137.  
  138.  
  139. //============================================================================
  140. //    • HMarqueeCaption                                [public]
  141. //============================================================================
  142. //    Parameterized constructor
  143.  
  144. HMarqueeCaption::HMarqueeCaption(
  145.     const SPaneInfo    &inPaneInfo,
  146.     ResIDT            inTextID,
  147.     ResIDT            inTextTraitsID,
  148.     Int16            inDelay,
  149.     Int16            inScrollAmount,
  150.     Boolean            inResetOnResize )
  151.         : LPane(inPaneInfo),
  152.         mStrHeight(0),
  153.         mLastEvent(0),
  154.         mGWorld(nil),
  155.         mTextLength(0),
  156.         mOffset(0),
  157.         mTextH(nil),
  158.         mTextID(inTextID),
  159.         mTextTraitsID(inTextTraitsID),
  160.         mDelay(inDelay),
  161.         mScrollAmount(inScrollAmount),
  162.         mResetOnResize(inResetOnResize)
  163. {
  164.     InitMarqueeCaption();
  165. }    
  166.  
  167.  
  168. //============================================================================
  169. //    • HMarqueeCaption                                [public]
  170. //============================================================================
  171. //    LStream constructor
  172.  
  173. HMarqueeCaption::HMarqueeCaption(
  174.     LStream    *inStream)
  175.         : LPane(inStream),
  176.         mStrHeight(0),
  177.         mTextH(nil),
  178.         mGWorld(nil),
  179.         mLastEvent(0),
  180.         mTextLength(0),
  181.         mOffset(0)
  182. {
  183.     inStream->ReadData( &mTextID, sizeof(ResIDT) );
  184.     inStream->ReadData( &mTextTraitsID, sizeof(ResIDT) );
  185.     inStream->ReadData( &mDelay, sizeof(Uint16) );
  186.     inStream->ReadData( &mScrollAmount, sizeof(Int16) );
  187.     inStream->ReadData( &mResetOnResize, sizeof(Boolean) );
  188.         
  189.     InitMarqueeCaption();
  190. }
  191.  
  192.  
  193. //============================================================================
  194. //    • ~HMarqueeCaption                                [public, virtual]
  195. //============================================================================
  196. //    Destructor
  197.  
  198. HMarqueeCaption::~HMarqueeCaption()
  199. {
  200.     if ( mTextH ) {
  201.         ::DisposeHandle(mTextH);
  202.     }
  203.  
  204.     DestroyGWorld();
  205. }
  206.  
  207.  
  208. //============================================================================
  209. //    • InitMarqueeCaption                            [private]
  210. //============================================================================
  211. //    Initializer
  212.  
  213. void
  214. HMarqueeCaption::InitMarqueeCaption()
  215. {
  216.     // create the GWorld
  217.     
  218.     AllocateGWorld();
  219.     
  220.     // get the text
  221.     
  222.     StResource    theTextH( 'TEXT', GetTextID() );
  223.     
  224.     // and use it
  225.     
  226.     SetTextHandle( (Handle)theTextH );
  227. }
  228.  
  229.  
  230. //============================================================================
  231. //    • SpendTime                                        [public, virtual]
  232. //============================================================================
  233. //    Draw the Caption
  234.  
  235. void
  236. HMarqueeCaption::SpendTime(
  237.     const EventRecord    &inMacEvent)
  238. {
  239.     // we're gonna have fun with modifier keys here :)
  240.     
  241.     // if command is down, we ignore the mDelay amount and just draw as often as
  242.     // SpendTime is called.  this should hopefully speed things up a bit (esp
  243.     // on faster computers)
  244.     
  245.     // if option is down, we scroll one more pixel than usual... makes the drawing
  246.     // a little more choppy, but faster.  cmd+opt is about as fast as you can get
  247.     
  248.     // if control is down, we just pause... a way to stop the action for a sec
  249.     
  250.     // and if shift is down, we chug in reverse. (to the right)
  251.     
  252.     // hopefully everything should be additive... like cmd-shift-opt would be
  253.     // every time through the loop going 1 more pixel to the right...a fast scroll
  254.     // to the right... and hitting control once in a while would pause you.
  255.         
  256.     // the only problem in here is that all is dependant upon the event loop
  257.     // and if some other app is hogging processor time (like a not-well behaved
  258.     // mac app would do) then these really don't have much impact on the speed of things
  259.     
  260.     // also, we don't "wrap" the scroll necessarily (I should work on this).  if we're
  261.     // going normal (to the left), eventually text does wrap around and continue along.
  262.     // but if shift is down, you can't go backwards to the beginning and have it
  263.     // wrap around to the end....maybe something to add later :)
  264.     
  265.     if ( (inMacEvent.modifiers & controlKey) != 0 )
  266.         return;
  267.     
  268.     if ( ((inMacEvent.modifiers & cmdKey) != 0)
  269.                 || (inMacEvent.when - GetLastEvent() ) > GetDelay() )
  270.     {
  271.         SetLastEvent( inMacEvent.when );
  272.         IncrementOffset( GetScrollAmount() );
  273.         
  274.         if ( (inMacEvent.modifiers & optionKey) != 0 ) {
  275.             IncrementOffset( 1 );
  276.         }
  277.         
  278.         if ( (inMacEvent.modifiers & shiftKey) != 0 ) {
  279.             IncrementOffset( -(GetScrollAmount() * 2) );
  280.             
  281.             if ( (inMacEvent.modifiers & optionKey) != 0 ) {
  282.                 IncrementOffset( -2 );    // have to remove 2..one to negate the above added
  283.                                         // and one more to actually do something
  284.             }
  285.         }
  286.                             
  287.         SDimension16    frameSize;
  288.         GetFrameSize( frameSize );
  289.     
  290.         if ( GetOffset() > (GetTextLength() + frameSize.width) )
  291.             SetOffset( 0 );
  292.         else if ( GetOffset() <= 0 )
  293.             SetOffset( GetTextLength() + frameSize.width );
  294.         
  295.         Draw( nil );
  296.     }
  297. }
  298.  
  299.  
  300. //============================================================================
  301. //    • Draw                                        [public, virtual]
  302. //============================================================================
  303. //    Draw the Caption. We have to override Draw so as to be able to use the
  304. //    GWorld for drawing.
  305.  
  306. void
  307. HMarqueeCaption::Draw(
  308.     RgnHandle    inSuperDrawRgnH )
  309. {
  310.     Rect    frame;
  311.  
  312.     // make sure we're in a state to bother drawing
  313.     
  314.     if ( IsVisible()  &&
  315.          FocusDraw()  &&
  316.          CalcPortFrameRect(frame)  &&
  317.          ((inSuperDrawRgnH == nil) || ::RectInRgn(&frame, inSuperDrawRgnH)) )
  318.     {         
  319.         // get our frame
  320.         
  321.         CalcLocalFrameRect( frame );
  322.  
  323.         // store off the GWorld
  324.         
  325.         CGrafPtr theSavePort;
  326.         GDHandle theSaveDevice;
  327.         ::GetGWorld( &theSavePort, &theSaveDevice );
  328.         
  329.         // convert
  330.         
  331.         Rect gwRect = frame;
  332.         ::LocalToGlobal( &topLeft(gwRect) );
  333.         ::LocalToGlobal( &botRight(gwRect) );
  334.         
  335.         // set up our GWorld for drawing
  336.                 
  337.         ::SetGWorld( mGWorld, nil );
  338.         ::SetOrigin( frame.left, frame.top );
  339.         ::LockPixels(::GetGWorldPixMap(mGWorld));
  340.         ApplyForeAndBackColors();
  341.         ::EraseRect(&frame);
  342.         
  343.         // draw it
  344.             
  345.         LPane::Draw( inSuperDrawRgnH );
  346.         
  347.         // restore
  348.         
  349.         ::SetGWorld(theSavePort, theSaveDevice);
  350.         
  351.         // and blit
  352.         
  353.         StColorState::Normalize();
  354.         ::CopyBits(&((GrafPtr)mGWorld)->portBits,
  355.                     &((GrafPtr)theSavePort)->portBits,
  356.                     &frame, &frame, srcCopy, nil);
  357.         
  358.         ::UnlockPixels(::GetGWorldPixMap(mGWorld));        
  359.     }
  360. }
  361.  
  362.  
  363. //============================================================================
  364. //    • DrawSelf                                    [protected, virtual]
  365. //============================================================================
  366. //    Draw the Caption
  367.  
  368. void
  369. HMarqueeCaption::DrawSelf()
  370. {
  371.     // get the rect and clip to it
  372.     Rect    frame;    
  373.  
  374.     CalcLocalFrameRect(frame);
  375.     ::InsetRect( &frame, 2, 2 );
  376.     StClipRgnState    clipSave( frame );
  377.  
  378.     // set the text traits
  379.     
  380.     UTextTraits::SetPortTextTraits( GetTextTraitsID() );
  381.     
  382.     // set up the colors
  383.     
  384.     RGBColor textColor;
  385.     ::GetForeColor(&textColor);
  386.     ApplyForeAndBackColors();
  387.     
  388.     if ( !IsActive() )
  389.     {
  390.         // lighten the text color a bit
  391.         
  392.         textColor.red = textColor.red + 65535 >> 1;
  393.         textColor.green = textColor.green + 65535 >> 1;
  394.         textColor.blue = textColor.blue + 65535 >> 1;
  395.     }    
  396.     
  397.     // restore the text color
  398.     
  399.     ::RGBForeColor(&textColor);
  400.  
  401.     // and draw the text
  402.     ::MoveTo( frame.right - GetOffset(), frame.top + GetStringHeight() );
  403.     StHandleLocker lock(mTextH);
  404.     ::DrawText( *mTextH, 0, ::GetHandleSize(mTextH) );
  405. }
  406.  
  407.  
  408. //============================================================================
  409. //    • Reset                                        [protected, virtual]
  410. //============================================================================
  411. //    Reset the status to default/starting values
  412.  
  413. void
  414. HMarqueeCaption::Reset()
  415. {
  416.     FontInfo    fontInfo;
  417.  
  418.     SetOffset( 0 );
  419.     SetLastEvent( 0 );
  420.     UTextTraits::SetPortTextTraits( GetTextTraitsID() );
  421.     ::GetFontInfo( &fontInfo );
  422.     SetStringHeight( fontInfo.ascent );
  423.     SetTextLength();    
  424. }
  425.  
  426.  
  427. //============================================================================
  428. //    • ActivateSelf                                [protected, virtual]
  429. //============================================================================
  430. //    We need to force a redraw when the pane becomes active so that it
  431. //    will draw properly.
  432.  
  433. void
  434. HMarqueeCaption::ActivateSelf()
  435. {
  436.     if ( mActive == triState_On ) {
  437.         Refresh();
  438.         StartRepeating();
  439.     }
  440. }
  441.  
  442.  
  443. //============================================================================
  444. //    • DeactivateSelf                            [protected, virtual]
  445. //============================================================================
  446. //    We need to force a redraw when the pane becomes deactivated
  447.  
  448. void
  449. HMarqueeCaption::DeactivateSelf()
  450. {
  451.     if ( mActive == triState_Off || mActive == triState_Latent ) {
  452.         Refresh();
  453.         StopRepeating();
  454.     }
  455. }
  456.  
  457.  
  458. //============================================================================
  459. //    • StripCRLF                                    [public, virtual]
  460. //============================================================================
  461. // Scans the text handle and strips out any carriage returns and/or
  462. // line feeds that it finds (they won't show up very well)
  463.  
  464. void
  465. HMarqueeCaption::StripCRLF()
  466. {
  467.     StHandleLocker lock(mTextH);
  468.     
  469.     Ptr thePtr = *mTextH;
  470.     
  471.     Size    theSize = ::GetHandleSize(mTextH);
  472.     
  473.     for ( Int32 i = 1; i <= theSize; ++i )
  474.     {
  475.         if ( (*thePtr == char_LineFeed) || (*thePtr == char_Return) ) {
  476.             *thePtr = char_Space;
  477.         }
  478.         
  479.         ++thePtr;
  480.     }
  481. }
  482.  
  483.  
  484. //============================================================================
  485. //    • SetTextHandle                                [public, virtual]
  486. //============================================================================
  487. // Sets the text to use to the given Handle. We make a copy of the given
  488. // Handle (so caller must dispose of the Handle)
  489.  
  490. void
  491. HMarqueeCaption::SetTextHandle( Handle inTextH )
  492. {
  493.     // If the new Handle is nil, we'll just stop right here.
  494.     
  495.     if ( inTextH == nil ) {
  496.         SignalPStr_("\pinTextH == nil");
  497.         return;
  498.     }
  499.     
  500.     // Just in case we're repeating, we should stop.
  501.     
  502.     StopRepeating();
  503.     
  504.     // get rid of any old text
  505.     
  506.     if ( mTextH != nil ) {
  507.         ::DisposeHandle(mTextH);
  508.         mTextH = nil;
  509.     }
  510.     
  511.     // make a copy of the new text
  512.     
  513.     mTextH = inTextH;
  514.     ThrowIfOSErr_(::HandToHand( &mTextH ));
  515.     
  516.     // strip any cr's and lf's
  517.     
  518.     StripCRLF();
  519.     
  520.     // reset things
  521.     
  522.     Reset();    
  523.     
  524.     // and start repeating
  525.     
  526.     StartRepeating();
  527. }
  528.  
  529.  
  530.  
  531. //============================================================================
  532. //    • AllocateGWorld                            [protected, virtual]
  533. //============================================================================
  534. //    Allocates our GWorld
  535.  
  536. void
  537. HMarqueeCaption::AllocateGWorld()
  538. {
  539.     // dispose of one, if needed
  540.     
  541.     DestroyGWorld();
  542.     
  543.     // we'll allocate a GWorld the size of our frame
  544.     
  545.     Rect frame;
  546.     CalcLocalFrameRect(frame);
  547.     ::LocalToGlobal( &topLeft(frame) );
  548.     ::LocalToGlobal( &botRight(frame) );
  549.     
  550.     QDErr err = ::NewGWorld( &mGWorld, 0, &frame, nil, nil, 0 );
  551.     if ( err == memFullErr ) {
  552.         // if our heap is full, try temporary memory
  553.         err  = ::NewGWorld( &mGWorld, 0, &frame, nil, nil, useTempMem );
  554.     }
  555.  
  556.     ThrowIfOSErr_(err);
  557.     ThrowIfNil_(mGWorld);
  558. }
  559.  
  560.  
  561.  
  562. //============================================================================
  563. //    • DestroyGWorld                                [protected, virtual]
  564. //============================================================================
  565. //    Disposes of our GWorld
  566.  
  567. void
  568. HMarqueeCaption::DestroyGWorld()
  569. {
  570.     if ( mGWorld != nil ) {
  571.         ::DisposeGWorld(mGWorld);
  572.         mGWorld = nil;
  573.     }
  574. }
  575.  
  576.  
  577. //============================================================================
  578. //    • ResizeFrameBy                                [public, virtual]
  579. //============================================================================
  580. //    If the frame size changes, we have to reallocate our GWorld
  581.  
  582. void
  583. HMarqueeCaption::ResizeFrameBy(
  584.     Int16        inWidthDelta,
  585.     Int16        inHeightDelta,
  586.     Boolean        inRefresh)
  587. {
  588.     // let the normal resizing occur
  589.     LPane::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh);
  590.     
  591.     // rellocate the GWorld
  592.     AllocateGWorld();
  593.  
  594.     // and reset if desired
  595.     
  596.     if ( GetResetOnResize() ) {
  597.         Reset();
  598.     }
  599. }
  600.  
  601.  
  602. // the following functions are declared inline in the header file. The #pragma
  603. // mark let's them show up in the CW IDE's function popup for ease of navigation
  604. // and reference. :-)
  605.  
  606. #pragma mark HMarqueeCaption::GetStringHeight
  607. #pragma mark HMarqueeCaption::SetStringHeight
  608. #pragma mark HMarqueeCaption::GetLastEvent
  609. #pragma mark HMarqueeCaption::SetLastEvent
  610. #pragma mark HMarqueeCaption::GetTextLength
  611. #pragma mark HMarqueeCaption::SetTextLength
  612. #pragma mark HMarqueeCaption::GetOffset
  613. #pragma mark HMarqueeCaption::SetOffset
  614. #pragma mark HMarqueeCaption::IncrementOffset
  615. #pragma mark HMarqueeCaption::GetTextID
  616. #pragma mark HMarqueeCaption::SetTextID
  617. #pragma mark HMarqueeCaption::GetTextTraitsID
  618. #pragma mark HMarqueeCaption::SetTextTraitsID
  619. #pragma mark HMarqueeCaption::GetDelay
  620. #pragma mark HMarqueeCaption::SetDelay
  621. #pragma mark HMarqueeCaption::GetScrollAmount
  622. #pragma mark HMarqueeCaption::SetScrollAmount
  623. #pragma mark HMarqueeCaption::GetResetOnResize
  624. #pragma mark HMarqueeCaption::SetResetOnResize